// wifi_prov_manager_v2.c - 增强版配网管理模块
#include <string.h>
#include <stdio.h>
#include "app_config.h"
#include "system/includes.h"
#include "wifi/wifi_connect.h"
#include "lwip.h"
#include "dhcp_srv/dhcp_srv.h"

#include "wifi_prov_config.h"
#include "wifi_prov_manager.h"

// =============== 内部状态管理 ===============
typedef struct {
    OS_MUTEX mtx;
    u8 inited;
    
    // 配置和回调
    wifi_prov_config_t config;
    wifi_prov_callbacks_t callbacks;
    wifi_prov_event_bridge_t bridge;
    
    // 状态机
    wifi_prov_state_t current_state;
    wifi_prov_state_t previous_state;
    wifi_prov_error_t last_error;
    
    // 超时管理
    u32 timeout_start_time;
    u32 current_timeout_ms;
    u8 timeout_active;
    u8 retry_count;
    
    // 配网信息
    char current_ssid[64];
    char current_password[64];
    u8 save_credentials;
    
    // 进度管理
    int progress;
    
    // 配网服务器状态
    u8 server_started;
    
} prov_ctx_t;

static prov_ctx_t g_ctx;

// =============== 日志宏 ===============
#define PLOG(fmt, ...) \
    do { \
        if (g_ctx.callbacks.on_error) { \
            char log_buf[256]; \
            snprintf(log_buf, sizeof(log_buf), "[prov] " fmt, ##__VA_ARGS__); \
            g_ctx.callbacks.on_error(WIFI_PROV_ERR_NONE, log_buf); \
        } else { \
            printf("[prov] " fmt, ##__VA_ARGS__); \
        } \
    } while (0)

// =============== 状态机管理 ===============
static void set_state(wifi_prov_state_t new_state)
{
    if (g_ctx.current_state == new_state) {
        return;
    }
    
    wifi_prov_state_t old_state = g_ctx.current_state;
    g_ctx.previous_state = old_state;
    g_ctx.current_state = new_state;
    
    PLOG("State changed: %d -> %d", old_state, new_state);
    
    // 通知状态变化
    if (g_ctx.callbacks.on_state_changed) {
        g_ctx.callbacks.on_state_changed(old_state, new_state);
    }
}

static void set_error(wifi_prov_error_t error, const char* message)
{
    g_ctx.last_error = error;
    PLOG("Error: %d - %s", error, message ? message : "Unknown error");
    
    if (g_ctx.callbacks.on_error) {
        g_ctx.callbacks.on_error(error, message);
    }
}

static void set_progress(int progress)
{
    if (progress < 0) progress = 0;
    if (progress > 100) progress = 100;
    
    g_ctx.progress = progress;
    
    if (g_ctx.callbacks.on_progress) {
        g_ctx.callbacks.on_progress(progress);
    }
}

// =============== 超时管理 ===============
static void start_timeout(u32 timeout_ms)
{
    g_ctx.timeout_start_time = timer_get_ms();
    g_ctx.current_timeout_ms = timeout_ms;
    g_ctx.timeout_active = 1;
}

static void stop_timeout(void)
{
    g_ctx.timeout_active = 0;
    g_ctx.current_timeout_ms = 0;
}

static int is_timeout(void)
{
    if (!g_ctx.timeout_active) {
        return 0;
    }
    
    u32 elapsed = timer_get_ms() - g_ctx.timeout_start_time;
    return (elapsed >= g_ctx.current_timeout_ms);
}

static void handle_timeout(wifi_prov_timeout_type_t timeout_type)
{
    stop_timeout();
    
    PLOG("Timeout: %d", timeout_type);
    
    if (g_ctx.callbacks.on_timeout) {
        g_ctx.callbacks.on_timeout(timeout_type);
    }
    
    // 根据超时类型处理
    switch (timeout_type) {
        case WIFI_PROV_TIMEOUT_AP_START:
            set_error(WIFI_PROV_ERR_AP_START_FAILED, "AP start timeout");
            set_state(WIFI_PROV_STATE_FAILED);
            break;
            
        case WIFI_PROV_TIMEOUT_WAIT_CREDENTIALS:
            set_error(WIFI_PROV_ERR_TIMEOUT, "Wait credentials timeout");
            set_state(WIFI_PROV_STATE_TIMEOUT);
            break;
            
        case WIFI_PROV_TIMEOUT_CONNECT:
            if (g_ctx.retry_count < g_ctx.config.max_retry_count) {
                g_ctx.retry_count++;
                PLOG("Retry connect: %d/%d", g_ctx.retry_count, g_ctx.config.max_retry_count);
                set_progress(20 + (g_ctx.retry_count * 20));
                // 重新尝试连接
                if (g_ctx.bridge.on_prov_connect_sta) {
                    g_ctx.bridge.on_prov_connect_sta(g_ctx.current_ssid, g_ctx.current_password);
                }
                start_timeout(g_ctx.config.timeouts.connect_timeout_ms);
            } else {
                set_error(WIFI_PROV_ERR_CONNECT_FAILED, "Connect failed after retries");
                set_state(WIFI_PROV_STATE_FAILED);
            }
            break;
            
        case WIFI_PROV_TIMEOUT_VERIFY:
            set_error(WIFI_PROV_ERR_NETWORK_ERROR, "Connection verification timeout");
            set_state(WIFI_PROV_STATE_FAILED);
            break;
    }
}

// =============== 状态机处理 ===============
static void handle_state_machine(void)
{
    switch (g_ctx.current_state) {
        case WIFI_PROV_STATE_IDLE:
            // 空闲状态，等待启动
            break;
            
        case WIFI_PROV_STATE_INIT:
            // 初始化完成，开始配网流程
            set_progress(10);
            set_state(WIFI_PROV_STATE_AP_STARTING);
            
            // 请求启动AP
            if (g_ctx.bridge.on_prov_start_ap) {
                g_ctx.bridge.on_prov_start_ap();
            }
            start_timeout(g_ctx.config.timeouts.ap_start_timeout_ms);
            break;
            
        case WIFI_PROV_STATE_AP_STARTING:
            // 检查AP启动超时
            if (is_timeout()) {
                handle_timeout(WIFI_PROV_TIMEOUT_AP_START);
            }
            break;
            
        case WIFI_PROV_STATE_AP_READY:
            // AP已就绪，等待配网信息
            set_progress(30);
            start_timeout(g_ctx.config.timeouts.wait_credentials_timeout_ms);
            break;
            
        case WIFI_PROV_STATE_CREDENTIALS_RECEIVED:
            // 收到配网信息，开始连接
            set_progress(50);
            set_state(WIFI_PROV_STATE_CONNECTING);
            
            // 请求连接STA
            if (g_ctx.bridge.on_prov_connect_sta) {
                g_ctx.bridge.on_prov_connect_sta(g_ctx.current_ssid, g_ctx.current_password);
            }
            start_timeout(g_ctx.config.timeouts.connect_timeout_ms);
            break;
            
        case WIFI_PROV_STATE_CONNECTING:
            // 检查连接超时
            if (is_timeout()) {
                handle_timeout(WIFI_PROV_TIMEOUT_CONNECT);
            }
            break;
            
        case WIFI_PROV_STATE_CONNECTED:
            // 连接成功
            set_progress(100);
            stop_timeout();
            
            if (g_ctx.callbacks.on_success) {
                g_ctx.callbacks.on_success(g_ctx.current_ssid);
            }
            break;
            
        case WIFI_PROV_STATE_FAILED:
        case WIFI_PROV_STATE_TIMEOUT:
            // 失败状态，停止超时
            stop_timeout();
            break;
            
        default:
            break;
    }
}

// =============== 定时任务 ===============
static void prov_timer_task(void* priv)
{
    while (1) {
        os_time_dly(100); // 100ms检查一次
        
        if (!g_ctx.inited) {
            continue;
        }
        
        OS_MUTEX_PEND(&g_ctx.mtx, 0);
        handle_state_machine();
        OS_MUTEX_POST(&g_ctx.mtx);
    }
}

// =============== 公共API实现 ===============
int wifi_prov_init(const wifi_prov_config_t* config)
{
    if (g_ctx.inited) {
        return 0; // 已经初始化
    }
    
    memset(&g_ctx, 0, sizeof(g_ctx));
    os_mutex_create(&g_ctx.mtx);
    
    // 设置默认配置
    if (config) {
        g_ctx.config = *config;
    } else {
        g_ctx.config = (wifi_prov_config_t)WIFI_PROV_DEFAULT_CONFIG();
    }
    
    g_ctx.current_state = WIFI_PROV_STATE_IDLE;
    g_ctx.progress = 0;
    g_ctx.inited = 1;
    
    // 启动定时任务
    thread_fork("prov_timer", 15, 512, 0, NULL, prov_timer_task, NULL);
    
    PLOG("Provisioning manager initialized");
    return 0;
}

int wifi_prov_start(void)
{
    if (!g_ctx.inited) {
        return -1;
    }
    
    OS_MUTEX_PEND(&g_ctx.mtx, 0);
    
    if (g_ctx.current_state != WIFI_PROV_STATE_IDLE) {
        OS_MUTEX_POST(&g_ctx.mtx);
        return -2; // 已经在运行
    }
    
    g_ctx.retry_count = 0;
    g_ctx.progress = 0;
    set_state(WIFI_PROV_STATE_INIT);
    
    OS_MUTEX_POST(&g_ctx.mtx);
    
    PLOG("Provisioning started");
    return 0;
}

int wifi_prov_stop(void)
{
    if (!g_ctx.inited) {
        return -1;
    }
    
    OS_MUTEX_PEND(&g_ctx.mtx, 0);
    
    stop_timeout();
    set_state(WIFI_PROV_STATE_IDLE);
    g_ctx.progress = 0;
    
    // 停止配网服务器
    if (g_ctx.server_started && g_ctx.bridge.on_prov_stop_ap) {
        g_ctx.bridge.on_prov_stop_ap();
    }
    g_ctx.server_started = 0;
    
    OS_MUTEX_POST(&g_ctx.mtx);
    
    PLOG("Provisioning stopped");
    return 0;
}

wifi_prov_state_t wifi_prov_get_state(void)
{
    if (!g_ctx.inited) {
        return WIFI_PROV_STATE_IDLE;
    }
    
    OS_MUTEX_PEND(&g_ctx.mtx, 0);
    wifi_prov_state_t state = g_ctx.current_state;
    OS_MUTEX_POST(&g_ctx.mtx);
    
    return state;
}

int wifi_prov_get_progress(void)
{
    if (!g_ctx.inited) {
        return 0;
    }
    
    OS_MUTEX_PEND(&g_ctx.mtx, 0);
    int progress = g_ctx.progress;
    OS_MUTEX_POST(&g_ctx.mtx);
    
    return progress;
}

wifi_prov_error_t wifi_prov_get_error(void)
{
    if (!g_ctx.inited) {
        return WIFI_PROV_ERR_NONE;
    }
    
    OS_MUTEX_PEND(&g_ctx.mtx, 0);
    wifi_prov_error_t error = g_ctx.last_error;
    OS_MUTEX_POST(&g_ctx.mtx);
    
    return error;
}

const char* wifi_prov_get_error_string(wifi_prov_error_t error)
{
    switch (error) {
        case WIFI_PROV_ERR_NONE: return "No error";
        case WIFI_PROV_ERR_INVALID_PARAM: return "Invalid parameter";
        case WIFI_PROV_ERR_AP_START_FAILED: return "AP start failed";
        case WIFI_PROV_ERR_CREDENTIALS_INVALID: return "Invalid credentials";
        case WIFI_PROV_ERR_CONNECT_FAILED: return "Connect failed";
        case WIFI_PROV_ERR_TIMEOUT: return "Timeout";
        case WIFI_PROV_ERR_NETWORK_ERROR: return "Network error";
        case WIFI_PROV_ERR_STORAGE_ERROR: return "Storage error";
        case WIFI_PROV_ERR_SERVER_ERROR: return "Server error";
        default: return "Unknown error";
    }
}

int wifi_prov_factory_reset(void)
{
    if (!g_ctx.inited) {
        return -1;
    }
    
    OS_MUTEX_PEND(&g_ctx.mtx, 0);
    
    stop_timeout();
    set_state(WIFI_PROV_STATE_FACTORY_RESET);
    
    // 清除存储的配网信息
    wifi_prov_nv_t nv;
    wifi_prov_nv_load(&nv);
    nv.magic = WIFI_PROV_MAGIC_FACTORY;
    wifi_prov_set_final_sta_and_normal_boot("", "");
    
    OS_MUTEX_POST(&g_ctx.mtx);
    
    PLOG("Factory reset completed");
    return 0;
}

int wifi_prov_set_callbacks(const wifi_prov_callbacks_t* callbacks)
{
    if (!g_ctx.inited) {
        return -1;
    }
    
    OS_MUTEX_PEND(&g_ctx.mtx, 0);
    
    if (callbacks) {
        g_ctx.callbacks = *callbacks;
    } else {
        memset(&g_ctx.callbacks, 0, sizeof(g_ctx.callbacks));
    }
    
    OS_MUTEX_POST(&g_ctx.mtx);
    return 0;
}

int wifi_prov_set_event_bridge(const wifi_prov_event_bridge_t* bridge)
{
    if (!g_ctx.inited) {
        return -1;
    }
    
    OS_MUTEX_PEND(&g_ctx.mtx, 0);
    
    if (bridge) {
        g_ctx.bridge = *bridge;
    } else {
        memset(&g_ctx.bridge, 0, sizeof(g_ctx.bridge));
    }
    
    OS_MUTEX_POST(&g_ctx.mtx);
    return 0;
}

const char* wifi_prov_get_connected_ssid(void)
{
    if (!g_ctx.inited) {
        return NULL;
    }
    
    OS_MUTEX_PEND(&g_ctx.mtx, 0);
    const char* ssid = g_ctx.current_ssid;
    OS_MUTEX_POST(&g_ctx.mtx);
    
    return ssid;
}

int wifi_prov_need_provisioning(void)
{
    wifi_prov_nv_t nv;
    int ret = wifi_prov_nv_load(&nv);
    return (ret != 0 || nv.magic == WIFI_PROV_MAGIC_NEED_PROV);
}

wifi_prov_desired_mode_t wifi_prov_get_desired_mode(void)
{
    wifi_prov_nv_t nv;
    wifi_prov_nv_load(&nv);
    
    if (nv.magic == WIFI_PROV_MAGIC_NEED_PROV) {
        return WIFI_PROV_DESIRED_AP;
    } else {
        return WIFI_PROV_DESIRED_STA;
    }
}

// =============== 事件处理 ===============
int wifi_prov_on_wifi_event(enum WIFI_EVENT event, void* arg)
{
    if (!g_ctx.inited) {
        return 0;
    }
    
    OS_MUTEX_PEND(&g_ctx.mtx, 0);
    
    switch (event) {
        case WIFI_EVENT_AP_START:
            if (g_ctx.current_state == WIFI_PROV_STATE_AP_STARTING) {
                stop_timeout();
                set_state(WIFI_PROV_STATE_AP_READY);
                g_ctx.server_started = 1;
            }
            break;
            
        case WIFI_EVENT_AP_STOP:
            if (g_ctx.server_started) {
                g_ctx.server_started = 0;
            }
            break;
            
        case WIFI_EVENT_STA_NETWORK_STACK_DHCP_SUCC:
            if (g_ctx.current_state == WIFI_PROV_STATE_CONNECTING) {
                stop_timeout();
                set_state(WIFI_PROV_STATE_CONNECTED);
            }
            break;
            
        case WIFI_EVENT_STA_DISCONNECT:
            if (g_ctx.current_state == WIFI_PROV_STATE_CONNECTING) {
                // 连接失败，由超时机制处理重试
            }
            break;
            
        default:
            break;
    }
    
    OS_MUTEX_POST(&g_ctx.mtx);
    return 0;
}

int wifi_prov_on_credentials(const char* ssid, const char* pwd, int save)
{
    if (!g_ctx.inited) {
        return -1;
    }
    
    if (!ssid || !ssid[0]) {
        set_error(WIFI_PROV_ERR_CREDENTIALS_INVALID, "SSID is empty");
        return -2;
    }
    
    OS_MUTEX_PEND(&g_ctx.mtx, 0);
    
    if (g_ctx.current_state != WIFI_PROV_STATE_AP_READY) {
        OS_MUTEX_POST(&g_ctx.mtx);
        return -3; // 状态不正确
    }
    
    // 保存配网信息
    strncpy(g_ctx.current_ssid, ssid, sizeof(g_ctx.current_ssid) - 1);
    g_ctx.current_ssid[sizeof(g_ctx.current_ssid) - 1] = '\0';
    
    if (pwd) {
        strncpy(g_ctx.current_password, pwd, sizeof(g_ctx.current_password) - 1);
        g_ctx.current_password[sizeof(g_ctx.current_password) - 1] = '\0';
    } else {
        g_ctx.current_password[0] = '\0';
    }
    
    g_ctx.save_credentials = save ? 1 : 0;
    g_ctx.retry_count = 0;
    
    stop_timeout();
    set_state(WIFI_PROV_STATE_CREDENTIALS_RECEIVED);
    
    OS_MUTEX_POST(&g_ctx.mtx);
    
    PLOG("Credentials received: ssid=%s, save=%d", ssid, save);
    return 0;
}
